package com.un.ebs.inventory.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.un.ebs.contract.dto.ContractVo;
import com.un.ebs.contract.service.ContractService;
import com.un.ebs.core.common.KeyValueDto;
import com.un.ebs.core.exception.BusinessEntityNotFoundException;
import com.un.ebs.core.exception.BusinessException;
import com.un.ebs.core.util.DateUtils;
import com.un.ebs.core.util.SecurityUtils;
import com.un.ebs.core.util.StringUtils;
import com.un.ebs.inventory.domain.*;
import com.un.ebs.inventory.dto.*;
import com.un.ebs.inventory.enums.InventoryTypeEnum;
import com.un.ebs.inventory.enums.OrderNoteTypeEnum;
import com.un.ebs.inventory.mapper.*;
import com.un.ebs.inventory.service.InventoryNoteService;
import com.un.ebs.inventory.service.InventoryNoteTypeService;
import com.un.ebs.inventory.service.InventoryService;
import com.un.ebs.inventory.service.WarehouseService;
import com.un.ebs.product.domain.ProductSku;
import com.un.ebs.product.service.ProductSkuService;
import com.un.ebs.production.domain.ProductionOrderExt;
import com.un.ebs.production.domain.ProductionWorkOrderOutExt;
import com.un.ebs.production.dto.ProductionOrderVo;
import com.un.ebs.production.service.ProductionOrderService;
import com.un.ebs.purchase.domain.PurchaseOrder;
import com.un.ebs.purchase.domain.PurchaseOrderItemExt;
import com.un.ebs.purchase.dto.PurchaseOrderVo;
import com.un.ebs.purchase.mapper.PurchaseOrderMapper;
import com.un.ebs.purchase.service.PurchaseOrderService;
import com.un.ebs.quality.CostCode;
import com.un.ebs.sale.domain.SaleDeliverNoteExt;
import com.un.ebs.sale.domain.SaleOrder;
import com.un.ebs.sale.dto.SaleDeliverNoteItemDto;
import com.un.ebs.sale.dto.SaleDeliverNoteUpdateDto;
import com.un.ebs.sale.enums.SaleOrderTypeEnum;
import com.un.ebs.sale.mapper.SaleOrderMapper;
import com.un.ebs.sale.service.SaleDeliverNoteService;
import com.un.ebs.sale.service.SaleOrderService;
import com.un.ebs.sys.domain.Personnel;
import com.un.ebs.sys.service.ConfigureService;
import com.un.ebs.sys.service.PersonnelService;
import com.un.ebs.workflow.service.WorkflowInstanceService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author liubo
 * @since 2020-05-23
 */
@Service
public class InventoryNoteServiceImpl extends ServiceImpl<InventoryNoteMapper, InventoryNote> implements InventoryNoteService {

    @Resource
    private InventoryNoteTypeService inventoryNoteTypeService;

    @Resource
    private PurchaseOrderService purchaseOrderService;

    @Resource
    private ProductionOrderService productionOrderService;

    @Resource
    private InventoryNoteItemBySaleMapper inventoryNoteItemBySaleMapper;

    @Resource
    private JxcViewMapper jxcViewMapper;

    @Resource
    private SaleOrderService saleOrderService;

    @Resource
    private SaleDeliverNoteService saleDeliverNoteService;

    @Resource
    private ConfigureService configureService;

    @Resource
    private PersonnelService personnelService;

    @Resource
    private ProductSkuService productSkuService;

    @Resource
    private WarehouseService warehouseService;

    @Resource
    private InventoryNoteItemMapper inventoryNoteItemMapper;

    @Resource
    private WorkflowInstanceService workflowInstanceService;

    @Resource
    private InventoryNoteExtMapper inventoryNoteExtMapper;

    @Resource
    private InventoryNoteItemExtMapper inventoryNoteItemExtMapper;

    @Resource
    private PurchaseOrderMapper purchaseOrderMapper;

    @Resource
    private SaleOrderMapper saleOrderMapper;

    @Resource
    private InventoryService inventoryService;

    @Resource
    private AccountMonthMapper accountMonthMapper;

    @Resource
    private ContractService contractService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addByIn(InventoryNoteAddDto req) {
        InventoryNoteByMoveAddDto newReq = new InventoryNoteByMoveAddDto();
        BeanUtils.copyProperties(req, newReq);
        return add(newReq, InventoryTypeEnum.IN);
    }

    @Transactional
    @Override
    public String addByPurchaseIn(String purchaseOrderId, String warehouseId, List<InventoryNoteItemDto> items) {

        PurchaseOrderVo order = purchaseOrderService.queryViewById(purchaseOrderId);
        if (order == null) {
            throw new BusinessEntityNotFoundException(purchaseOrderId, "采购订单");
        }

        // 服务采购订单可以先收货再做合同
        if (order.getIsFrame() && !order.getIsServices()) {
            throw new BusinessException("当前采购订单未指定正式采购合同。");
        }
        ContractVo contract = contractService.queryViewByCode(order.getContractCode());
        if (contract == null) {
            throw new BusinessEntityNotFoundException(order.getContractCode(), "采购合同");
        }
        if (!contract.getAuditStatus()) {
            throw new BusinessException("采购合同未审核。");
        }

        //采购订单的业务类别
        InventoryNoteTypeExt noteTypeExt = inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PURCHASE);

        InventoryNoteByMoveAddDto obj = new InventoryNoteByMoveAddDto();
        obj.setWarehouseId(warehouseId);
        obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        obj.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PURCHASE_IN).getId());
        obj.setType(InventoryTypeEnum.IN);
        obj.setRelationNoteCode(order.getCode());
        obj.setRelationNoteId(order.getId());
        obj.setRelationNoteTypeId(noteTypeExt.getId());
        obj.setContractCode(order.getContractCode());

        if (StringUtils.isNullOrEmpty(items)) {
            throw new BusinessException("采购收货明细不能为空。");
        }
        if (StringUtils.isNullOrEmpty(order.getItems())) {
            throw new BusinessException("采购订单明细不能为空。");
        }

        List<InventoryNoteItemDto> inventoryNoteItems = new ArrayList<>();
        for (InventoryNoteItemDto item : items) {
            if (item.getQty() == null) {
                throw new BusinessException(String.format("请指定收货数量。"));
            }
            if (item.getQty() == 0) {
                throw new BusinessException("收货数量不能大于零。");
            }

            // 订单数量
            double sumQty = order.getItems().stream().filter(s -> item.getSkuId().equals(s.getSkuId())).mapToDouble(s -> s.getQty()).sum();

            // 当前收货数量
            double sumDeliverQty = order.getItems().stream().filter(s -> item.getSkuId().equals(s.getSkuId())).findFirst().get().getDeliverQty();

            if (item.getQty() > (sumQty - sumDeliverQty)) {
                throw new BusinessException(String.format("收货数量不能大于剩余未收货数量。"));
            }

            inventoryNoteItems.add(new InventoryNoteItemDto(null,
                    item.getSkuId(),
                    item.getQty(),
                    order.getItems().stream().filter(s -> s.getSkuId().equals(item.getSkuId())).findFirst().get().getPrice())
            );
        }
        obj.setItems(inventoryNoteItems);
        obj.setSubmitStatus(true);
        return add(obj, InventoryTypeEnum.IN);
    }

    @Deprecated
    @Override
    public void addServicePurchaseInAndOut(String purchaseOrderId, String productionOrderId, String warehouseId, String skuId, double qty) {
        PurchaseOrderVo purchaseOrder = purchaseOrderService.queryViewById(purchaseOrderId);
        if (purchaseOrder == null) {
            throw new BusinessEntityNotFoundException(purchaseOrderId, "采购订单");
        }
        if (purchaseOrder.getSumQty().intValue() == purchaseOrder.getSumAcceptQty().intValue()) {
            throw new BusinessException("采购订单已收货。");
        }
        if (purchaseOrder.getSumQty() < purchaseOrder.getSumAcceptQty()) {
            throw new BusinessException("采购订单数量超过收货数量。");
        }
        if (purchaseOrder.getItems().stream().filter(s -> s.getSkuId().equals(skuId)).count() <= 0) {
            throw new BusinessException("指定的物料在采购订单中不存在。");
        }
        ProductionOrderVo productionOrder = productionOrderService.queryViewById(productionOrderId);
        if (productionOrder == null) {
            throw new BusinessEntityNotFoundException(productionOrderId, "生产订单");
        }

        double price = 0;
        Optional<PurchaseOrderItemExt> item = purchaseOrder.getItems().stream().filter(s -> s.getSkuId().equals(skuId)).findFirst();
        if (item.isPresent()) {
            price = item.get().getPrice();
        } else {
            throw new BusinessException("指定的物料在采购订单不存在。");
        }

        // 直接采购入库
        InventoryNote noteIn = new InventoryNote();
        noteIn.setWarehouseId(warehouseId);
        noteIn.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PURCHASE_IN).getId());
        noteIn.setInventoryType(InventoryTypeEnum.IN);
        noteIn.setRelationNoteId(purchaseOrderId);
        noteIn.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PURCHASE).getId());
        noteIn.setRelationNoteCode(purchaseOrder.getCode());
        noteIn.setCode(inventoryNoteTypeService.queryCode(noteIn.getNoteTypeId(), baseMapper.maxCode()));
        noteIn.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        noteIn.setPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        noteIn.setSubmitAt(SecurityUtils.getUserContent().getId());
        noteIn.setSubmitAtName(SecurityUtils.getUserContent().getPersonnelName());
        noteIn.setSubmitTime(new Date());
        noteIn.setSubmitStatus(true);
        noteIn.setAuditAt(SecurityUtils.getUserContent().getId());
        noteIn.setAuditAtName(SecurityUtils.getUserContent().getPersonnelName());
        noteIn.setAuditTime(DateUtils.parseDate(new Date(), "yyyy-MM-dd"));
        noteIn.setAuditStatus(true);
        noteIn.setContractCode(purchaseOrder.getContractCode());
        noteIn.insert();

        InventoryNoteItem noteItemIn = new InventoryNoteItem();
        noteItemIn.setNoteId(noteIn.getId());
        noteItemIn.setSkuId(skuId);
        noteItemIn.setQty(qty);
        noteItemIn.setPrice(price);
        noteItemIn.insert();

        // 直接领料出库
        InventoryNote noteOut = new InventoryNote();
        noteOut.setWarehouseId(warehouseId);
        noteOut.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_BOM_USER).getId());
        noteOut.setInventoryType(InventoryTypeEnum.OUT);
        noteOut.setRelationNoteId(productionOrderId);
        noteOut.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION).getId());
        noteOut.setRelationNoteCode(productionOrder.getCode());
        noteOut.setCode(inventoryNoteTypeService.queryCode(noteOut.getNoteTypeId(), baseMapper.maxCode()));
        noteOut.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        noteOut.setPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        noteOut.setSubmitAt(SecurityUtils.getUserContent().getId());
        noteOut.setSubmitAtName(SecurityUtils.getUserContent().getPersonnelName());
        noteOut.setSubmitTime(new Date());
        noteOut.setSubmitStatus(true);
        noteOut.setAuditAt(SecurityUtils.getUserContent().getId());
        noteOut.setAuditAtName(SecurityUtils.getUserContent().getPersonnelName());
        noteOut.setAuditTime(new Date());
        noteOut.setAuditStatus(true);
        noteOut.insert();

        InventoryNoteItem noteItemOut = new InventoryNoteItem();
        noteItemOut.setNoteId(noteOut.getId());
        noteItemOut.setSkuId(skuId);
        noteItemOut.setQty(qty);
        noteItemOut.setPrice(price);
        noteItemOut.insert();
    }

    @Override
    public void addServiceOut(String productionOrderId, String warehouseId, String skuId, double qty) {

    }

    @Override
    public String addByProductionIn(String productionOrderId, String skuId, String warehouseId, Double qty) {
        ProductionOrderVo order = productionOrderService.queryViewById(productionOrderId);
        if (order == null) {
            throw new BusinessEntityNotFoundException(productionOrderId, "生产订单");
        }
        if (!order.getSubmitStatus()) {
            throw new BusinessException("生产订单没有提交。");
        }

        if (!(order.getSaleOrderType() == SaleOrderTypeEnum.REPAIR || order.getSaleOrderType() == SaleOrderTypeEnum.SERVICE)) {
            if (order.getBomUserQty().longValue() < order.getBomRequirementQty().longValue()) {
                throw new BusinessException("物料没有领完，不能入库。");
            }
        }

        // 检查是否有未审核的领料
        checkBomUser(order);

//        if (order.getProductionCostMoney() == 0) {
//            throw new BusinessException("入库成本不能为零。");
//        }

        InventoryNoteAddDto note = new InventoryNoteAddDto();
        note.setRelationNoteCode(order.getCode());
        note.setRelationNoteId(order.getId());
        note.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION).getId());
        note.setWarehouseId(warehouseId);
        note.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        note.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_IN).getId());

        String noteId = inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_IN).getId();

        double totalQty = order.getItems().stream().filter(s -> skuId.equals(s.getSkuId())).mapToDouble(s -> s.getQty()).sum();
        double totalDeliverQty = queryItemByRelationNoteId(productionOrderId).stream().filter(s -> skuId.equals(s.getSkuId()) && s.getNoteId().equals(noteId)).mapToDouble(s -> s.getQty()).sum();
        if (totalQty < totalDeliverQty + qty) {
            throw new BusinessException(String.format("生产订单 %s 已全部入库，不能超范围入库。", order.getCode()));
        }
        List<InventoryNoteItemDto> items = new ArrayList<>();
        InventoryNoteItemDto item = new InventoryNoteItemDto();
        item.setSkuId(skuId);
        item.setQty(qty);
        item.setPrice(order.getProductionCostMoney());
        items.add(item);
        note.setItems(items);
        String id = addByIn(note);
        submit(id);
        return id;
    }

    @Override
    public String addBySaleOut(InventoryNoteBySaleOutDto req) {
        Warehouse warehouse = warehouseService.queryById(req.getWarehouseId());
        if (!warehouse.getIsProduct()) {
            throw new BusinessException(String.format("销售出库业务只能从成品库出库，当前指定的仓库【%s】不是成品库！", warehouse.getName()));
        }

        InventoryNoteByMoveAddDto obj = new InventoryNoteByMoveAddDto();
        obj.setWarehouseId(req.getWarehouseId());
        obj.setPersonnelId(req.getPersonnelId());

        if (!StringUtils.isNullOrEmpty(req.getSaleOrderId())) {
            SaleOrder order = saleOrderService.queryById(req.getSaleOrderId());
            if (order == null) {
                throw new BusinessException("销售订单无效。");
            }
            if (!order.getSubmitStatus()) {
                throw new BusinessException("指定的销售订单未提交。");
            }
            if (order.getDeliverStatus()) {
                throw new BusinessException("指定的销售订单已完成交付。");
            }
            List<InventoryNoteTypeExt> types = inventoryNoteTypeService.queryByType(OrderNoteTypeEnum.SaleOrder, InventoryTypeEnum.OUT, true);
            if (StringUtils.isNullOrEmpty(types)) {
                throw new BusinessException("库存业务类别异常。");
            }
            obj.setRelationNoteTypeId(types.get(0).getId());
        }
        if (StringUtils.isNullOrEmpty(req.getContractCode())) {
            throw new BusinessException("销售合同号不能为空。");
        }
        obj.setContractCode(req.getContractCode());
        obj.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.SALE_OUT).getId());
        obj.setItems(req.getItems());

        return add(obj, InventoryTypeEnum.OUT);
    }

    @Override
    public void addBySaleOut(String saleOrderId, String skuId, String warehouseId, Double qty, String outTypeId) {
        List<InventoryExt> list = inventoryService.queryBySku(skuId);
        double sumQty = list.stream().filter(s -> s.getIsStore() == true).mapToDouble(s -> s.getQty()).sum();
        if (qty > sumQty) {
            throw new BusinessException("库存不足，不能出库。");
        }

        SaleOrder saleOrder = saleOrderService.queryById(saleOrderId);
        if (saleOrder == null) {
            throw new BusinessEntityNotFoundException(saleOrderId, "销售订单");
        }
        if (!saleOrder.getSubmitStatus()) {
            throw new BusinessException("销售订单没有提交。");
        }

        sumQty = saleOrderService.queryItem(saleOrderId, -1, 1).getRecords().stream().filter(s -> skuId.equals(s.getSkuId())).mapToDouble(s -> s.getQty()).sum();
        if (qty > sumQty) {
            throw new BusinessException("出库数量不能大于订单数量。");
        }

        Double inventoryQty = baseMapper.selectCanSaleInventory(skuId, warehouseId);
        if (inventoryQty == null) {
            throw new BusinessException("没有足够的库存。");
        }
        if (inventoryQty < qty) {
            throw new BusinessException("没有足够的库存。");
        }

        InventoryNoteByMoveAddDto obj = new InventoryNoteByMoveAddDto();
        obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        obj.setRelationNoteId(saleOrderId);
        obj.setRelationNoteCode(saleOrder.getCode());
        obj.setRelationNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.SALE).getId());
        obj.setNoteTypeId(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.SALE_OUT).getId());
        obj.setWarehouseId(warehouseId);
        List<InventoryNoteItemDto> items = new ArrayList<>();
        InventoryNoteItemDto item = new InventoryNoteItemDto();
        item.setSkuId(skuId);
        item.setQty(qty);
        items.add(item);
        obj.setItems(items);
        String id = add(obj, InventoryTypeEnum.OUT);
        submit(id);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addByOut(InventoryNoteAddDto req) {
        InventoryNoteByMoveAddDto newReq = new InventoryNoteByMoveAddDto();
        BeanUtils.copyProperties(req, newReq);
        return add(newReq, InventoryTypeEnum.OUT);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addByMove(InventoryNoteByMoveAddDto req) {
        return add(req, InventoryTypeEnum.OUT);
    }

    public String add(InventoryNoteByMoveAddDto req, InventoryTypeEnum typeEnum) {
        if (req.getNoteType() != null) {
            req.setNoteTypeId(inventoryNoteTypeService.queryOneByType(req.getNoteType()).getId());
        }

        InventoryNoteTypeExt type = inventoryNoteTypeService.queryById(req.getNoteTypeId());
        if (type == null) {
            throw new BusinessEntityNotFoundException(req.getNoteTypeId(), "库存业务类型");
        }
        if (StringUtils.isNullOrEmpty(req.getItems())) {
            throw new BusinessException("明细不能为空。");
        }
        if (StringUtils.isNullOrEmpty(req.getWarehouseId())) {
            throw new BusinessException("请指定仓库。");
        }

        InventoryNote obj = new InventoryNote();
        obj.setWarehouseId(req.getWarehouseId());
        if (!StringUtils.isNullOrEmpty(req.getWarehouseToId())) {
            obj.setWarehouseToId(req.getWarehouseToId());
        }
        obj.setNoteTypeId(req.getNoteTypeId());
        obj.setInventoryType(convert(typeEnum));
        obj.setRelationNoteId(req.getRelationNoteId());
        obj.setRelationNoteTypeId(req.getRelationNoteTypeId());
        obj.setRelationNoteCode(req.getRelationNoteCode());
        obj.setRemark(req.getRemark());
        obj.setCode(inventoryNoteTypeService.queryCode(req.getNoteTypeId(), baseMapper.maxCode()));
        obj.setContractCode(req.getContractCode());

        if (typeEnum == InventoryTypeEnum.OUT && req.getIsRebuild()) {
            obj.setIsRebuild(true);
        }

        if (StringUtils.isNullOrEmpty(req.getPersonnelId())) {
            obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
            obj.setPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        } else {
            obj.setPersonnelId(req.getPersonnelId());
            Personnel personnel = personnelService.queryById(req.getPersonnelId());
            if (personnel == null) {
                throw new BusinessException("指定的人员信息无效。");
            }
            obj.setPersonnelName(personnel.getName());
        }
        obj.insert();

        for (InventoryNoteItemDto item : req.getItems()) {
            if (item.getQty() == null) {
                throw new BusinessException("单据数量不能为空。");
            }
            if (item.getQty() == 0) {
                throw new BusinessException("数量不能为零。");
            }
            InventoryNoteItem objItem = new InventoryNoteItem();
            objItem.setNoteId(obj.getId());
            objItem.setSkuId(item.getSkuId());
            objItem.setQty(item.getQty());
            objItem.setPrice(item.getPrice());
            objItem.insert();
        }
        String id = obj.getId();
        if (req.getSubmitStatus()) {
            submit(id);
        }
        return id;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String update(InventoryNoteUpdateDto req) {

        if (req.getNoteType() != null) {
            req.setNoteTypeId(inventoryNoteTypeService.queryOneByType(req.getNoteType()).getId());
        }

        InventoryNote obj = getById(req.getId());
        if (obj == null) {
            obj = new InventoryNote();
            obj.setCode(inventoryNoteTypeService.queryCode(req.getNoteTypeId(), baseMapper.maxCode()));
        } else {
            if (obj.getSubmitStatus()) {
                throw new BusinessException("单据已提交，不能修改。");
            }
            if (obj.getIsDelete()) {
                throw new BusinessException("单据已删除，不能修改。");
            }
        }

        if (StringUtils.isNullOrEmpty(req.getPersonnelId())) {
            obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
            obj.setPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        } else {
            Personnel personnel = personnelService.queryById(req.getPersonnelId());
            if (personnel == null) {
                throw new BusinessEntityNotFoundException(req.getPersonnelId(), "员工");
            }
            obj.setPersonnelId(req.getPersonnelId());
            obj.setPersonnelName(personnel.getName());
        }
        obj.setWarehouseId(req.getWarehouseId());
        obj.setWarehouseToId(req.getWarehouseToId());
        obj.setNoteTypeId(req.getNoteTypeId());
        obj.setRelationNoteId(req.getRelationNoteId());
        obj.setRelationNoteCode(req.getRelationNoteCode());
        obj.setRelationNoteTypeId(req.getRelationNoteTypeId());
        obj.setInventoryType(convert(req.getType()));
        obj.setRemark(req.getRemark());
        obj.setIsDelete(false);
        obj.setSubmitStatus(false);
        obj.insertOrUpdate();

        // 清除订单明细
        LambdaQueryWrapper<InventoryNoteItem> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItem::getNoteId, obj.getId());
        inventoryNoteItemMapper.delete(lq);

        for (InventoryNoteItemDto item : req.getItems()) {
            if (item.getQty() == null) {
                throw new BusinessException("单据数量不能为空。");
            }
            if (item.getQty() == 0) {
                throw new BusinessException("数量不能为零。");
            }
            InventoryNoteItem objItem = new InventoryNoteItem();
            objItem.setId(item.getId());
            objItem.setNoteId(obj.getId());
            objItem.setSkuId(item.getSkuId());
            objItem.setQty(item.getQty());
            objItem.insertOrUpdate();
        }
        return obj.getId();
    }

    @Override
    public void delete(String id) {
        InventoryNote obj = baseMapper.selectById(id);
        if (obj.getSubmitStatus()) {
            throw new BusinessException("单据已提交，不能删除。");
        }
        InventoryNoteTypeExt type = inventoryNoteTypeService.queryById(obj.getNoteTypeId());
        if (type == null) {
            throw new BusinessException("当前单据的单据类型定义无效。");
        }
        getBaseMapper().deleteById(id);
    }

    private void checkBomUser(ProductionOrderExt order) {
        List<String> typeIds = new ArrayList<>();

        typeIds.add(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_BOM_USER).getId());
        typeIds.add(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.REPAIR_USER).getId());

        LambdaQueryWrapper<InventoryNote> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNote::getRelationNoteId, order.getId());
        lq.in(InventoryNote::getNoteTypeId, typeIds);
        for (InventoryNote note : baseMapper.selectList(lq)) {
            if (note.getIsDelete()) {
                continue;
            }

            if (note.getSubmitStatus() == false) {
                throw new BusinessException("当前生产订单相关的领料单 【" + note.getCode() + "】 没有提交并审核，需要提交并审核后才能进行执行此操作。");
            }
            if (note.getAuditStatus() == false) {
                throw new BusinessException("当前生产订单相关的领料单 【" + note.getCode() + "】 没有审核，需要审核后才能进行执行此操作。");
            }
        }

        List<ProductionWorkOrderOutExt> seqSkuItems = productionOrderService.queryItemSeqSkuByOrderId(order.getId());
        for (ProductionWorkOrderOutExt item : seqSkuItems) {
            BigDecimal planQty = new BigDecimal(item.getPlanWorkQty()).multiply(new BigDecimal(item.getSeqUserQty().doubleValue())).setScale(2, RoundingMode.HALF_UP);
            BigDecimal realQty = new BigDecimal(item.getPurchaseQty()).setScale(2, RoundingMode.HALF_UP);
            if (!planQty.equals(realQty)) {
                throw new BusinessException(String.format("委外工序【%s：%s】未按需求【计划用量：%s，实际采购：%s】进行采购。", item.getSeqItemCode(), item.getSeqItemName()));
            }
            LambdaQueryWrapper<InventoryNoteItemExt> itemQuery = Wrappers.lambdaQuery();
            itemQuery.eq(InventoryNoteItemExt::getRelationNoteId, order.getId());
            itemQuery.in(InventoryNoteItemExt::getNoteTypeId, typeIds);
            itemQuery.eq(InventoryNoteItemExt::getSkuId, item.getSeqSkuId());
            itemQuery.eq(InventoryNoteItemExt::getSubmitStatus, true);
            itemQuery.eq(InventoryNoteItemExt::getAuditStatus, true);
            BigDecimal outQty = new BigDecimal(inventoryNoteItemExtMapper.selectList(itemQuery).stream().mapToDouble(s -> s.getQty()).sum()).setScale(2, RoundingMode.HALF_UP);
            if (!planQty.equals(outQty)) {
                throw new BusinessException(String.format("委外工序【%s：%s】未按需求【计划用量：%s，实际出库：%s】进行出库。", item.getSeqItemCode(), item.getSeqItemName(), planQty, outQty));
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void submit(String id) {
        InventoryNote obj = getById(id);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(id, "单据");
        }
        if (obj.getSubmitStatus()) {
            throw new BusinessException("单据已提交，不能重复提交。");
        }
        if (obj.getIsDelete()) {
            throw new BusinessException("单据已删除，不能执行此操作。");
        }
        InventoryNoteTypeExt noteTypeExt = inventoryNoteTypeService.queryById(obj.getNoteTypeId());
        if (noteTypeExt == null) {
            throw new BusinessException("业务类型配置数据没有找到。");
        }
        if (isCloseAccount(new Date())) {
            throw new BusinessException(String.format("【%s年%s月】的会计期间已关账，不能执行此操作。", DateUtils.getYear(new Date()), DateUtils.getMonth(new Date())));
        }

        List<InventoryNoteItem> list = queryItemById(id);
        for (InventoryNoteItem item : list) {
            ProductSku sku = productSkuService.queryById(item.getSkuId());
            Double qty;
            switch (obj.getInventoryType()) {
                case IN:
                    inventoryService.lockByPlus(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty());
                    break;
                case OUT:
                    if (item.getQty() > 0) {
                        qty = baseMapper.selectInventoryQty(item.getSkuId(), obj.getWarehouseId());
                        if (qty == null) {
                            if (sku != null) {
                                throw new BusinessException(String.format("【%s】没有库存可出库。", sku.getSkuCode()));
                            } else {
                                throw new BusinessException(String.format("【%s】没有库存可出库。", sku.getSkuCode()));
                            }

                        }
                        if (qty < item.getQty()) {
                            throw new BusinessException(String.format("【%s】没有库存可出库。", sku.getSkuCode()));
                        }
                    }
                    inventoryService.lockByReduce(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty());
                    break;
                default:
                    throw new BusinessException("单据的库存类别不正确。");
            }

            if (inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PURCHASE_IN).getId().equals(noteTypeExt.getId())) {
                String configValue = configureService.getValueByCode(CostCode.quality_check_proportion_by_purchase);
                if (!StringUtils.isNullOrEmpty(configValue)) {
                    Double value = new BigDecimal(item.getQty() * Double.parseDouble(configValue) / 100d).setScale(0, RoundingMode.HALF_UP).doubleValue();
                    item.setPlanCheckQty(value <= 0 ? 1d : value);
                    item.updateById();
                }
            }
        }
        obj.setSubmitAt(SecurityUtils.getUserContent().getId());
        obj.setSubmitAtName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setSubmitStatus(true);
        obj.setSubmitTime(new Date());

        // 如果定义了审批流程，则开始流程
        if (!StringUtils.isNullOrEmpty(noteTypeExt.getWorkflowId())) {
            String workflowInstanceId = workflowInstanceService.start(noteTypeExt.getWorkflowId(), obj.getInventoryType(), obj.getId(), obj.getCode());
            obj.setWorkflowPassStatus(false);
            obj.setWorkflowInstanceId(workflowInstanceId);
        } else {
            obj.setWorkflowPassStatus(true);
        }

        obj.updateById();

    }

    @Override
    public void submitCancel(String id) {
        submitCancel(id, true);
    }

    @Override
    public void submitCancel(String id, boolean rebuildCheck) {
        InventoryNote obj = getById(id);
        if (!obj.getSubmitStatus()) {
            throw new BusinessException("单据未已提交，不能撤销。");
        }
        if (obj.getAuditStatus()) {
            throw new BusinessException("单据已审核，不能撤销。");
        }
        if (obj.getIsDelete()) {
            throw new BusinessException("单据已删除，不能撤销。");
        }
        InventoryNoteTypeExt type = inventoryNoteTypeService.queryById(obj.getNoteTypeId());
        if (type == null) {
            throw new BusinessException("当前单据的单据类型定义无效。");
        }
        if (type.getInventoryType() == InventoryTypeEnum.MOVE_IN) {
            throw new BusinessException("调拨入库单不能直接撤销提交，需要将相应的调拨出库单【" + obj.getRelationNoteCode() + "】撤销后，调拨入库单会自动作废。");
        }
        if (type.getInventoryType() == InventoryTypeEnum.PRODUCTION_BOM_USER && obj.getIsRebuild() && rebuildCheck) {
            throw new BusinessException(String.format("此领料单属于返工再造产品的出库单，需要在撤销生产订单【%s】时，才能将此领料单自动撤销。", obj.getRelationNoteCode()));
        }
        List<InventoryNoteItem> list = queryItemById(id);
        for (InventoryNoteItem item : list) {
            switch (obj.getInventoryType()) {
                case IN:
                    inventoryService.lockByPlus(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty() - item.getQty() * 2);
                    break;
                case OUT:
                    inventoryService.lockByReduce(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty() - item.getQty() * 2);
                    break;
//                case MOVE:
//                    inventoryService.lockByMove(item.getId(), obj.getWarehouseId(), obj.getWarehouseToId(), item.getSkuId(), item.getQty() - item.getQty() * 2);
//                    break;
                default:
                    throw new BusinessException("单据的库存类别不正确。");
            }
        }
        obj.setSubmitAt(null);
        obj.setSubmitAtName(null);
        obj.setSubmitStatus(false);
        obj.setSubmitTime(null);
        obj.updateById();

        obj.deleteById();
    }

    @Override
    public void submitAll() {
        LambdaQueryWrapper<InventoryNote> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNote::getSubmitStatus, false);
        //lq.eq(InventoryNote::getAuditStatus,false);
        lq.eq(InventoryNote::getIsDelete, false);
        lq.orderByAsc(InventoryNote::getCode);
        List<InventoryNote> list = baseMapper.selectList(lq);
        for (InventoryNote obj : list) {
            submit(obj.getId());
            audit(obj.getId());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void audit(String id) {
        InventoryNoteExt objExt = queryViewById(id);
        if (!(objExt.getSubmitStatus() && objExt.getAuditStatus() == false)) {
            throw new BusinessException("单据已提交且未审核，才能执行此操作。");
        }
        if (InventoryTypeEnum.PURCHASE_IN.getCode() == objExt.getNoteTypeCode()) {
            List<InventoryNoteItemExt> items = queryItemById(id, -1, 1).getRecords().stream().filter(s -> StringUtils.isNullOrEmpty(s.getCheckNoteId())).collect(Collectors.toList());
            if (items.size() > 0) {
                throw new BusinessException("质检未完成，请确认所有项都完成了质检确认。\r\n" + items.stream().map(s -> s.getSkuCode() + " : " + s.getNameAs() + "\r\n").collect(Collectors.joining()));
            }
        }

        InventoryNote obj = getById(id);
        if (!(obj.getSubmitStatus() && obj.getAuditStatus() == false)) {
            throw new BusinessException("单据已提交且未审核，才能执行此操作。");
        }
        if (isCloseAccount(new Date())) {
            throw new BusinessException(String.format("【%s年%s月】的会计期间已关账，不能执行此操作。", DateUtils.getYear(new Date()), DateUtils.getMonth(new Date())));
        }

        List<InventoryNoteItem> list = queryItemById(id);
        for (InventoryNoteItem item : list) {
            switch (obj.getInventoryType()) {
                case IN:
                    inventoryService.plus(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty() - item.getCheckNotPassQty(), item.getPrice(), true);
                    break;
                case OUT:
                    inventoryService.reduce(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty() - item.getCheckNotPassQty(), item.getPrice(), true);
                    item.setPrice(inventoryService.queryCostPrice(item.getSkuId(), DateUtils.getYear(new Date()), DateUtils.getMonth(new Date())));
                    item.updateById();
                    break;
                default:
                    throw new BusinessException("单据的库存类别不正确。");
            }
        }
        obj.setAuditAt(SecurityUtils.getUserContent().getId());
        obj.setAuditAtName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setAuditStatus(true);
        obj.setAuditTime(new Date());
        obj.updateById();

        //如果是调拨出库，则自动生成调拨入库，并提交
        InventoryNoteTypeExt type = inventoryNoteTypeService.queryById(obj.getNoteTypeId());
        if (type == null) {
            throw new BusinessException("单据类别不正确。");
        }
        if (type.getInventoryType() == InventoryTypeEnum.MOVE_OUT) {
            createMoveIn(obj, list);
        }
        if (type.getInventoryType() == InventoryTypeEnum.PRODUCTION_IN) {
            productionOrderService.deliver(obj.getRelationNoteId());
        }

        //如果是销售退货，则自动生成销售发货单
        // TODO: 2021/12/16 销售退货单审核后，自动生成销售发货单，因为销售合同的交付是按销售发货单算的。此逻辑设计上存在瑕疵，应该做解耦，或者销售合同的交付只以销售出库来计算。
        if(obj.getNoteTypeId().equals(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.SALE_OUT).getId()) && !StringUtils.isNullOrEmpty(obj.getBackParentId())){
            SaleDeliverNoteExt deliverNote =  saleDeliverNoteService.queryNoteByInventoryNoteId(obj.getBackParentId());
            if(deliverNote==null){
                throw new BusinessException("原始销售出库单没有找到。");
            }
            SaleDeliverNoteUpdateDto saleDeliver = new SaleDeliverNoteUpdateDto();
            saleDeliver.setContractCode(obj.getContractCode());
            saleDeliver.setDeliverAdd(deliverNote.getDeliverAdd());
            saleDeliver.setDeliverTypeDict(deliverNote.getDeliverTypeDict());
            saleDeliver.setDeliverDate(new Date());
            saleDeliver.setLinkman(deliverNote.getLinkman());
            saleDeliver.setPhone(deliverNote.getPhone());
            saleDeliver.setPurchaseOrderCode(deliverNote.getPurchaseOrderCode());
            saleDeliver.setRemark("销售退货单");

            List<SaleDeliverNoteItemDto> items = new ArrayList<>();
            for(InventoryNoteItem item : list){
                SaleDeliverNoteItemDto objItem = new SaleDeliverNoteItemDto();
                objItem.setSkuId(item.getSkuId());
                objItem.setQty(item.getQty() - item.getCheckNotPassQty());
                objItem.setInventoryNoteItemId(item.getId());
                items.add(objItem);
            }
            saleDeliver.setItems(items);
            saleDeliverNoteService.submit(saleDeliverNoteService.save(saleDeliver));
        }
    }

    /**
     * 调拨出库审核时，执行此方法，用于同步生产调拨入库，并自动提交。
     *
     * @param moveOutNote
     * @param moveOutItems
     */
    private void createMoveIn(InventoryNote moveOutNote, List<InventoryNoteItem> moveOutItems) {

        InventoryNoteTypeExt typeIn = inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.MOVE_IN);
        if (typeIn == null) {
            throw new BusinessException("没有定义调拨入库的业务类型。");
        }

        InventoryNote objNew = new InventoryNote();
        objNew.setCode(inventoryNoteTypeService.queryCode(typeIn.getId(), baseMapper.maxCode()));
        objNew.setRelationNoteTypeId(moveOutNote.getNoteTypeId());
        objNew.setRelationNoteCode(moveOutNote.getCode());
        objNew.setRelationNoteId(moveOutNote.getId());
        objNew.setNoteTypeId(typeIn.getId());
        objNew.setInventoryType(InventoryTypeEnum.IN);
        objNew.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        objNew.setPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        objNew.setSubmitStatus(true);
        objNew.setSubmitAtName(SecurityUtils.getUserContent().getPersonnelName());
        objNew.setSubmitAt(SecurityUtils.getUserContent().getId());
        objNew.setSubmitTime(new Date());
        objNew.setWarehouseId(moveOutNote.getWarehouseToId());
        objNew.setWorkflowPassStatus(true);
        objNew.insert();

        for (InventoryNoteItem item : moveOutItems) {
            InventoryNoteItem itemNew = new InventoryNoteItem();
            itemNew.setNoteId(objNew.getId());
            itemNew.setSkuId(item.getSkuId());
            itemNew.setQty(item.getQty());
            itemNew.setPrice(item.getPrice());
            itemNew.insert();

            inventoryService.lockByPlus(item.getId(), moveOutNote.getWarehouseToId(), item.getSkuId(), item.getQty());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditCancel(String id) {
        InventoryNote obj = getById(id);
        if (!(obj.getSubmitStatus() && obj.getAuditStatus())) {
            throw new BusinessException("单据必须是已提交且已审核，才能执行此操作。");
        }
        if (!StringUtils.isNullOrEmpty(obj.getFinanceCode())) {
            throw new BusinessException("单据已生成财务凭证，不可以撤销审核。");
        }
        if (isCloseAccount(obj.getAuditTime())) {
            throw new BusinessException(String.format("【%s年%s月】的会计期间已关账，不能撤销。", DateUtils.getYear(obj.getAuditTime()), DateUtils.getMonth(obj.getAuditTime())));
        }
        String noteTypeId = inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.SALE_OUT).getId();
        if (obj.getNoteTypeId().equals(noteTypeId)) {
            if (saleDeliverNoteService.queryDeliverStatus(id)) {
                throw new BusinessException("当前销售出库单已发货，如果要继续此操作，请先撤销发货单。");
            }
        }
        if(obj.getNoteTypeId().equals(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.PRODUCTION_BOM_USER).getId())){
            double planQty = baseMapper.sumProductionPlanQty(obj.getRelationNoteId());
            double realQty = baseMapper.sumProductionInQty(obj.getRelationNoteId());
            if(planQty<=0){
                throw new BusinessException("计划生产数量为零。");
            }
            if(planQty == realQty){
                throw new BusinessException("当前生产订单已全部入库，领料成本已计入生产成本，不能撤销领料单。");
            }
        }

        for (InventoryNoteItem item : queryItemById(id)) {
            switch (obj.getInventoryType()) {
                case IN:
                    inventoryService.reduce(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty(), item.getPrice(), false);
                    break;
                case OUT:
                    inventoryService.plus(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty(), item.getPrice(), false);
                    break;
//                case MOVE:
//                    inventoryService.lockByMove(item.getId(), obj.getWarehouseToId(), obj.getWarehouseId(), item.getSkuId(), item.getQty());
//                    break;
                default:
                    throw new BusinessException("单据的库存类别不正确。");
            }
        }
        obj.setAuditStatus(false);
        obj.setAuditAt(null);
        obj.setAuditAtName(null);
        obj.setAuditTime(null);
        obj.setSubmitStatus(false);
        obj.setSubmitAtName(null);
        obj.setSubmitTime(null);
        obj.setSubmitAt(null);
        obj.updateById();

        moveAuditCancel(obj);
    }

    /**
     * 调拨出库单撤销审核时，需要执行此方法，用于同时撤销调拨入库
     *
     * @param note
     */
    private void moveAuditCancel(InventoryNote note) {
        //如果是调拨出库，则自动生成调拨入库，并提交
        InventoryNoteTypeExt type = inventoryNoteTypeService.queryById(note.getNoteTypeId());
        if (type == null) {
            throw new BusinessException("单据类别不正确。");
        }

        if (!(type.getInventoryType() == InventoryTypeEnum.MOVE_OUT || type.getInventoryType() == InventoryTypeEnum.MOVE_IN)) {
            return;
        }

        LambdaQueryWrapper<InventoryNote> lq = Wrappers.lambdaQuery();
        if (type.getInventoryType() == InventoryTypeEnum.MOVE_OUT) {
            lq.eq(InventoryNote::getRelationNoteId, note.getId());
        } else if (type.getInventoryType() == InventoryTypeEnum.MOVE_IN) {
            throw new BusinessException("已审核的调拨入库单不能直接撤销。");
        } else {
            throw new BusinessException("单据的库存类别不正确。");
        }
        lq.eq(InventoryNote::getIsDelete, false);
        InventoryNote obj = baseMapper.selectOne(lq);
        if (obj == null) {
            throw new BusinessException("撤销调拨出库单时，没有找到相应的调拨入库单。");
        }

        if (!obj.getInventoryType().equals(InventoryTypeEnum.IN)) {
            throw new BusinessException("调拨入库单的库存类别不正确。");
        }

        for (InventoryNoteItem item : queryItemById(obj.getId())) {
            inventoryService.lockByPlus(item.getId(), obj.getWarehouseId(), item.getSkuId(), item.getQty() - (item.getQty() * 2));
        }
        obj.setSubmitAt(null);
        obj.setSubmitTime(null);
        obj.setSubmitAtName(null);
        obj.setSubmitStatus(false);
        obj.updateById();
        obj.deleteById();
    }

    @Override
    public void workflowPass(String noteId, String workflowInstanceId) {
        InventoryNote obj = baseMapper.selectById(noteId);
        if (obj == null) {
            throw new BusinessEntityNotFoundException(noteId, "单据");
        }

        if (!obj.getSubmitStatus()) {
            throw new BusinessException("单据已没有提交，不能执行此操作。");
        }
        if (obj.getAuditStatus()) {
            throw new BusinessException("单据已审核，不能执行此操作。");
        }
        if (!workflowInstanceId.equals(obj.getWorkflowInstanceId())) {
            throw new BusinessException("单据的流程实例与当前待办事宜的流程实例不符合。");
        }
        obj.setWorkflowPassStatus(true);
        obj.updateById();
    }

    @Override
    public void addByBack(InventoryNoteBackDto req) {
        InventoryNoteVo note = queryViewById(req.getNoteId());
        if (note == null) {
            throw new BusinessEntityNotFoundException(req.getNoteId(), "库存单据");
        }
        if (!note.getAuditStatus()) {
            throw new BusinessException("库存单据没有审核。");
        }
        if(!StringUtils.isNullOrEmpty(note.getBackParentId())){
            throw new BusinessException("当前单据本身是退货单，不能再退。");
        }

        if(!StringUtils.isNullOrEmpty(req.getItems())){
            if(req.getItems().stream().map(s->s.getSkuId()).distinct().count() != req.getItems().size()){
                throw new BusinessException("退单明细不能有重复的 Sku");
            }
        }

        InventoryNote obj = new InventoryNote();
        obj.setCode(inventoryNoteTypeService.queryCode(note.getNoteTypeId(), baseMapper.maxCode()));
        obj.setPersonnelId(SecurityUtils.getUserContent().getPersonnelId());
        obj.setPersonnelName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setInventoryType(note.getInventoryType());
        obj.setNoteTypeId(note.getNoteTypeId());
        obj.setRelationNoteTypeId(note.getRelationNoteTypeId());
        obj.setRelationNoteCode(note.getRelationNoteCode());
        obj.setRelationNoteId(note.getRelationNoteId());
        obj.setWarehouseId(note.getWarehouseId());
        obj.setWarehouseToId(note.getWarehouseToId());
        obj.setContractCode(note.getContractCode());
        obj.setSubmitStatus(true);
        obj.setSubmitAt(SecurityUtils.getUserContent().getId());
        obj.setSubmitAtName(SecurityUtils.getUserContent().getPersonnelName());
        obj.setSubmitTime(new Date());
        obj.setBackParentId(note.getId());
        obj.setWorkflowPassStatus(true);
        obj.insert();

        if(StringUtils.isNullOrEmpty(req.getItems())){
            for (InventoryNoteItemExt item : note.getItems()) {
                InventoryNoteItem objItem = new InventoryNoteItem();
                objItem.setSkuId(item.getSkuId());
                objItem.setQty(item.getQty() - (item.getQty() * 2));
                objItem.setPrice(item.getPrice());
                objItem.setNoteId(obj.getId());
                objItem.insert();
            }
        }else{
            for(InventoryNoteBackItemDto dto : req.getItems()){
                Optional<InventoryNoteItemExt> item =  note.getItems().stream().filter(s->s.getSkuId().equals(dto.getSkuId())).findFirst();
                if(!item.isPresent()){
                    throw new BusinessException("退货条目在原始单据中不存在。");
                }
                if(item.get().getQty() < Math.abs(dto.getQty())){
                    throw new BusinessException("退货条目的数量不能超过原有单据数量。");
                }
                if(dto.getQty()==0){
                    throw new BusinessException("退货数量不能为零。");
                }
                if(dto.getQty()>0){
                    throw new BusinessException("退货数量必须为负数。");
                }
                InventoryNoteItem objItem = new InventoryNoteItem();
                objItem.setSkuId(dto.getSkuId());
                objItem.setPrice(item.get().getPrice());
                objItem.setQty(dto.getQty());
                objItem.setNoteId(obj.getId());
                objItem.insert();
            }
        }

    }

    @Override
    public void addByBack(String id) {
        InventoryNoteBackDto obj = new InventoryNoteBackDto();
        obj.setNoteId(id);
        addByBack(obj);
    }

    @Override
    public void updateFinanceCode(String id, String financeId, String financeCode) {
        InventoryNote note = baseMapper.selectById(id);
        if (note == null) {
            throw new BusinessEntityNotFoundException(id, "库存单据");
        }
        if (note.getIsDelete()) {
            throw new BusinessException("单据已作废。");
        }
        if (note.getSubmitStatus() == false || note.getAuditStatus() == false) {
            throw new BusinessException("单据没有提交或审核。");
        }
        note.setFinanceCode(financeCode);
        note.setFinanceId(financeId);
        note.setFinanceSendTime(new Date());
        note.updateById();
    }

    @Override
    public void updateFinanceCode(int year, int month, String entId, InventoryTypeEnum type, String financeId, String financeCode) {
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getAccountYear, year);
        lq.eq(InventoryNoteItemExt::getAccountMonth, month);
        lq.eq(InventoryNoteItemExt::getEntId, entId);
        lq.eq(InventoryNoteItemExt::getNoteType, type);
        lq.eq(InventoryNoteItemExt::getIsDelete, false);
        lq.eq(InventoryNoteItemExt::getSubmitStatus, true);
        lq.eq(InventoryNoteItemExt::getAuditStatus, true);
        List<String> ids = inventoryNoteItemExtMapper.selectList(lq).stream().map(s -> s.getNoteId()).collect(Collectors.toList());

        if (StringUtils.isNullOrEmpty(ids)) {
            return;
        }

        InventoryNote note = new InventoryNote();
        note.setFinanceCode(financeCode);
        note.setFinanceId(financeId);
        note.setFinanceSendTime(new Date());
        baseMapper.update(note, new UpdateWrapper<InventoryNote>().in("id", ids));
    }

    @Override
    public void updateFinanceCode(int year, int month, InventoryTypeEnum type, String financeId, String financeCode) {
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getAccountYear, year);
        lq.eq(InventoryNoteItemExt::getAccountMonth, month);
        lq.eq(InventoryNoteItemExt::getNoteType, type);
        lq.eq(InventoryNoteItemExt::getIsDelete, false);
        lq.eq(InventoryNoteItemExt::getSubmitStatus, true);
        lq.eq(InventoryNoteItemExt::getAuditStatus, true);
        List<String> ids = inventoryNoteItemExtMapper.selectList(lq).stream().map(s -> s.getNoteId()).collect(Collectors.toList());

        if (StringUtils.isNullOrEmpty(ids)) {
            return;
        }

        InventoryNote note = new InventoryNote();
        note.setFinanceCode(financeCode);
        note.setFinanceId(financeId);
        note.setFinanceSendTime(new Date());
        baseMapper.update(note, new UpdateWrapper<InventoryNote>().in("id", ids));
    }

    @Override
    public void qualityNotPass(String inventoryNoteItemId, Double notPassQty, String checkNoteId) {
        InventoryNoteItem item = inventoryNoteItemMapper.selectById(inventoryNoteItemId);
        if (item == null) {
            throw new BusinessEntityNotFoundException(inventoryNoteItemId, "单据明细");
        }
        if (!StringUtils.isNullOrEmpty(item.getCheckNoteId())) {
            throw new BusinessException("不能重复检验。");
        }
        InventoryNote note = baseMapper.selectById(item.getNoteId());
        if (!note.getSubmitStatus() && !note.getIsDelete()) {
            throw new BusinessException("单据没有提交。");
        }
        if (note.getAuditStatus()) {
            throw new BusinessException("单据已审核。");
        }

        item.setCheckNoteId(checkNoteId);
        item.setCheckNotPassQty(notPassQty);
        item.updateById();
    }

    @Override
    public InventoryNote queryById(String id) {
        return getBaseMapper().selectById(id);
    }

    @Override
    public InventoryNoteVo queryViewById(String id) {
        InventoryNoteExt obj = inventoryNoteExtMapper.selectById(id);
        if (obj == null) {
            return null;
        }
        InventoryNoteVo ret = new InventoryNoteVo();
        BeanUtils.copyProperties(obj, ret);
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getNoteId, id);
        ret.setItems(inventoryNoteItemExtMapper.selectList(lq));
        return ret;
    }

    @Override
    public IPage<InventoryNoteExt> query(String searchText, InventoryTypeEnum type, String noteTypeId, int pageSize, int pageIndex) {
        Page<InventoryNoteExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(noteTypeId)) {
            lq.eq(InventoryNoteExt::getNoteTypeId, noteTypeId);
        }
        if (type != null) {
            if (type != InventoryTypeEnum.NotDefine) {
                switch (type) {
                    case IN:
                    case OUT:
                        lq.eq(InventoryNoteExt::getInventoryType, type);
                    default:
                        lq.eq(InventoryNoteExt::getNoteTypeCode, type.getCode());
                }
            }
        }
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.eq(InventoryNoteExt::getCode, searchText.trim()).or()
                    .eq(InventoryNoteExt::getRelationNoteCode, searchText.trim());
        }
        lq.orderByDesc(InventoryNoteExt::getCreateTime);
        return inventoryNoteExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<InventoryNoteExt> query(String searchText, String relationNoteId, Boolean auditStatus, InventoryTypeEnum type, Integer pageSize, Integer pageIndex) {
        Page<InventoryNoteExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteExt::getIsDelete, false);
        if (type != null) {
            lq.eq(InventoryNoteExt::getInventoryType, type);
        }
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.like(InventoryNoteExt::getCode, searchText)
                    .or().like(InventoryNoteExt::getPersonnelName, searchText)
                    .or().like(InventoryNoteExt::getRelationNoteCode, searchText);
        }
        if (!StringUtils.isNullOrEmpty(relationNoteId)) {
            lq.eq(InventoryNoteExt::getRelationNoteId, relationNoteId);
        }
        if (auditStatus != null) {
            if (auditStatus) {
                lq.eq(InventoryNoteExt::getAuditStatus, false);
            }
        }
        lq.orderByDesc(InventoryNoteExt::getCreateTime);
        return inventoryNoteExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<InventoryNoteExt> query(InventoryNoteQueryRequest req) {
        Page<InventoryNoteExt> page = new Page(req.getPageIndex(), req.getPageSize());
        LambdaQueryWrapper<InventoryNoteExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteExt::getIsDelete, false);
        if (req.getNoteType() != null) {
            lq.eq(InventoryNoteExt::getNoteTypeCode, req.getNoteType().getCode());
        }
        if (req.getInventoryType() != null) {
            lq.eq(InventoryNoteExt::getInventoryType, req.getInventoryType());
        }
        if (req.getAuditStatus() != null) {
            if (req.getAuditStatus()) {
                lq.eq(InventoryNoteExt::getAuditStatus, true);
            }
        }
        if (!StringUtils.isNullOrEmpty(req.getEntId())) {
            lq.eq(InventoryNoteExt::getEntId, req.getEntId());
        }
        if (req.getYear() != null) {
            lq.eq(InventoryNoteExt::getAccountYear, req.getYear());
        }
        if (req.getMonth() != null) {
            lq.eq(InventoryNoteExt::getAccountMonth, req.getMonth());
        }
        if (!StringUtils.isNullOrEmpty(req.getWarehouseId())) {
            lq.eq(InventoryNoteExt::getWarehouseId, req.getWarehouseId());
        }
        if (!StringUtils.isNullOrEmpty(req.getSearchText())) {
            lq.like(InventoryNoteExt::getCode, req.getSearchText().trim())
                    .or().like(InventoryNoteExt::getPersonnelName, req.getSearchText().trim())
                    .or().like(InventoryNoteExt::getContractCode, req.getSearchText().trim())
                    .or().like(InventoryNoteExt::getRelationNoteCode, req.getSearchText().trim());
        }
        lq.orderByDesc(InventoryNoteExt::getCode);
        return inventoryNoteExtMapper.selectPage(page, lq);
    }

    @Override
    public List<InventoryNoteExt> queryByRelationNoteId(String relationNoteId) {
        return baseMapper.selectByRelationId(relationNoteId);
    }

    @Override
    public IPage<InventoryNoteItemExt> queryItem(String searchText, InventoryTypeEnum type, String noteTypeId, int pageSize, int pageIndex) {
        Page<InventoryNoteItemExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.eq(InventoryNoteItemExt::getCode, searchText).or()
                    .eq(InventoryNoteItemExt::getRelationNoteCode, searchText).or()
                    .eq(InventoryNoteItemExt::getSkuCode, searchText);
        }
        if (!StringUtils.isNullOrEmpty(noteTypeId)) {
            lq.eq(InventoryNoteItemExt::getNoteTypeId, noteTypeId);
        }
        if (type != null) {
            if (InventoryTypeEnum.NotDefine != type) {
                lq.eq(InventoryNoteItemExt::getInventoryType, type);
            }
        }
        lq.orderByDesc(InventoryNoteItemExt::getCreateTime);
        return inventoryNoteItemExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<InventoryNoteItemExt> queryItem(InventoryNoteItemQueryRequest req) {
        Page<InventoryNoteItemExt> page = new Page<>(req.getPageIndex(), req.getPageSize());
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(req.getSkuId())) {
            lq.eq(InventoryNoteItemExt::getSkuId, req.getSkuId());
        }
        if (!StringUtils.isNullOrEmpty(req.getNoteTypeId())) {
            lq.eq(InventoryNoteItemExt::getNoteTypeId, req.getNoteTypeId());
        }
        if (!StringUtils.isNullOrEmpty(req.getEntId())) {
            lq.eq(InventoryNoteItemExt::getEntId, req.getEntId());
        }
        if (!StringUtils.isNullOrEmpty(req.getWarehouseId())) {
            lq.eq(InventoryNoteItemExt::getWarehouseId, req.getWarehouseId());
        }
        if (req.getInventoryType() != null) {
            if (InventoryTypeEnum.NotDefine != req.getInventoryType()) {
                lq.eq(InventoryNoteItemExt::getInventoryType, req.getInventoryType());
            }
        }
        if (req.getYear() != null) {
            lq.eq(InventoryNoteItemExt::getAccountYear, req.getYear());
        }
        if (req.getMonth() != null) {
            lq.eq(InventoryNoteItemExt::getAccountMonth, req.getMonth());
        }
        if (req.getAuditStatus() != null) {
            if (req.getAuditStatus()) {
                lq.eq(InventoryNoteItemExt::getAuditStatus, req.getAuditStatus());
            }
        }
        if (!StringUtils.isNullOrEmpty(req.getSearchText())) {
            lq.and(s -> s.eq(InventoryNoteItemExt::getCode, req.getSearchText().trim()).or()
                    .eq(InventoryNoteItemExt::getRelationNoteCode, req.getSearchText().trim()).or()
                    .eq(InventoryNoteItemExt::getSkuCode, req.getSearchText().trim()).or()
                    .eq(InventoryNoteItemExt::getContractCode, req.getSearchText().trim()));
        }
        lq.orderByDesc(InventoryNoteItemExt::getAccountYear).orderByAsc(InventoryNoteItemExt::getAccountMonth).orderByDesc(InventoryNoteItemExt::getAuditTime);
        return inventoryNoteItemExtMapper.selectPage(page, lq);
    }

    @Override
    public List<InventoryNoteItem> queryItemById(String id) {
        LambdaQueryWrapper<InventoryNoteItem> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItem::getNoteId, id);
        return inventoryNoteItemMapper.selectList(lq);
    }

    public List<InventoryNoteItem> queryItemByRelationNoteId(String id) {
        LambdaQueryWrapper<InventoryNote> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNote::getRelationNoteId, id);
        lq.eq(InventoryNote::getSubmitStatus, true);
        List<String> ids = baseMapper.selectList(lq).stream().map(s -> s.getId()).collect(Collectors.toList());

        if (StringUtils.isNullOrEmpty(ids)) {
            return new ArrayList<>();
        }

        LambdaQueryWrapper<InventoryNoteItem> lqItem = Wrappers.lambdaQuery();
        lqItem.in(InventoryNoteItem::getNoteId, ids);
        return inventoryNoteItemMapper.selectList(lqItem);
    }

    @Override
    public IPage<InventoryNoteItemExt> queryItemById(String id, Integer pageSize, Integer pageIndex) {
        Page<InventoryNoteItemExt> page = new Page(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getNoteId, id);
        lq.orderByAsc(InventoryNoteItemExt::getSkuCode);
        return inventoryNoteItemExtMapper.selectPage(page, lq);
    }

    @Override
    public List<KeyValueDto> queryEnt() {
        List<KeyValueDto> ret;
        LambdaQueryWrapper<PurchaseOrder> purchaseQuery = Wrappers.lambdaQuery();
        purchaseQuery.eq(PurchaseOrder::getIsDelete, false);
        purchaseQuery.orderByAsc(PurchaseOrder::getSupplierEntName);
        ret = purchaseOrderMapper.selectList(purchaseQuery).stream().map(s -> KeyValueDto.value(s.getSupplierEntId(), "供应商 - " + s.getSupplierEntName())).distinct().collect(Collectors.toList());

        LambdaQueryWrapper<SaleOrder> saleQuery = Wrappers.lambdaQuery();
        saleQuery.eq(SaleOrder::getIsDelete, false);
        saleQuery.orderByAsc(SaleOrder::getCustomerEntName);
        ret.addAll(saleOrderMapper.selectList(saleQuery).stream().map(s -> KeyValueDto.value(s.getCustomerEntId(), "客户 - " + s.getCustomerEntName())).distinct().collect(Collectors.toList()));

        return ret.stream().distinct().collect(Collectors.toList());

    }

    @Override
    public InventoryNoteItemExt queryItemByItemId(String id) {
        return inventoryNoteItemExtMapper.selectById(id);
    }

    @Override
    public IPage<JxcView> queryJxc(String searchText, Integer pageSize, Integer pageIndex) {
        Page<JxcView> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<JxcView> lq = Wrappers.lambdaQuery();
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.eq(JxcView::getSkuCode, searchText);
        }
        lq.orderByAsc(JxcView::getSkuCode);
        return jxcViewMapper.selectPage(page, lq);
    }

    @Override
    public List<InventoryNoteExt> queryNotSendFinanceByType(int year, int month, InventoryTypeEnum... noteType) {
        LambdaQueryWrapper<InventoryNoteExt> lq = Wrappers.lambdaQuery();
        lq.in(InventoryNoteExt::getNoteTypeCode, noteType);
        lq.eq(InventoryNoteExt::getSubmitStatus, true);
        lq.eq(InventoryNoteExt::getAuditStatus, true);
        lq.eq(InventoryNoteExt::getAccountYear, year);
        lq.eq(InventoryNoteExt::getAccountMonth, month);
        lq.eq(InventoryNoteExt::getIsDelete, false);
        lq.isNull(InventoryNoteExt::getFinanceCode);
        lq.orderByAsc(InventoryNoteExt::getAuditTime);
        return inventoryNoteExtMapper.selectList(lq);
    }

    @Override
    public List<InventoryNoteItemExt> queryItemExtByRelationNoteId(String id) {
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getRelationNoteId, id);
        return inventoryNoteItemExtMapper.selectList(lq);
    }

    @Override
    public InventoryNoteVo queryRebuildNoteByRelation(String relationId) {
        return queryViewById(baseMapper.selectIdByRelationIdAndRebuild(relationId));
    }

    @Override
    public List<InventoryNoteItemExt> queryItemExtByContractCode(String contractCode) {
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getContractCode, contractCode);
        return inventoryNoteItemExtMapper.selectList(lq);
    }

    @Override
    public IPage<InventoryNoteItemExt> queryItemExtByNoteTypeId(String noteTypeId, String skuId, int pageSize, int pageIndex) {
        Page<InventoryNoteItemExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getNoteTypeId, noteTypeId);
        lq.eq(InventoryNoteItemExt::getSkuId, skuId);
        lq.orderByAsc(InventoryNoteItemExt::getSkuCode);
        return inventoryNoteItemExtMapper.selectPage(page, lq);
    }

    @Override
    public IPage<InventoryNoteItemExt> queryItemExtByNoteType(InventoryTypeEnum type, String skuId, int pageSize, int pageIndex) {
        Page<InventoryNoteItemExt> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteItemExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemExt::getNoteTypeId, inventoryNoteTypeService.queryOneByType(type).getId());
        lq.eq(InventoryNoteItemExt::getSkuId, skuId);
        lq.orderByAsc(InventoryNoteItemExt::getAuditTime);
        return inventoryNoteItemExtMapper.selectPage(page, lq);
    }

    private InventoryTypeEnum convert(InventoryTypeEnum type) {
        switch (type) {
            case IN:
            case PRODUCTION_IN:
            case PURCHASE_IN:
            case MOVE_IN:
                return InventoryTypeEnum.IN;
            case OUT:
            case SALE_OUT:
            case PRODUCTION_BOM_USER:
            case PRODUCTION_USER:
            case MOVE_OUT:
                return InventoryTypeEnum.OUT;
            default:
                throw new BusinessException(String.format("当前业务【%s】无法转换为出入库标识。", type.getDesc()));
        }
    }

    @Override
    public boolean isCloseAccount(Date dt) {
        LambdaQueryWrapper<AccountMonth> lq = Wrappers.lambdaQuery();
        lq.eq(AccountMonth::getAccountYear, DateUtils.getYear(dt));
        lq.eq(AccountMonth::getAccountMonth, DateUtils.getMonth(dt));
        AccountMonth accountMonth = accountMonthMapper.selectOne(lq);
        if (accountMonth == null) {
            return false;
        }
        if(DateUtils.differentDays(accountMonth.getEndDate(),dt)>0){
            return false;
        }else{
            return accountMonth.getCloseStatus();
        }
    }

    @Override
    public Double queryCostMoney(InventoryTypeEnum type, int year, int month) {
        Double ret = baseMapper.selectCostMoney(type.getCode(), year, month, SecurityUtils.getTenantId());
        return ret == null ? 0 : ret;
    }

    @Override
    public IPage<InventoryNoteItemBySale> querySaleCanInvoice(String entId,String inventoryNoteCode, Integer pageSize, Integer pageIndex) {
        Page<InventoryNoteItemBySale> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteItemBySale> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteItemBySale::getEntId, entId);

        if(!StringUtils.isNullOrEmpty(inventoryNoteCode)){
            lq.like(InventoryNoteItemBySale::getInventoryNoteCode,inventoryNoteCode);
        }
        lq.ne(InventoryNoteItemBySale::getInvoiceNotQty, 0);
        //lq.eq(InventoryNoteItemBySale::getContractCode, contractCode);
        return inventoryNoteItemBySaleMapper.selectPage(page, lq);
    }

    @Override
    public IPage<InventoryNoteItemBySale> querySale(String searchText, String entId, String month, Boolean isNotInvoice, Integer pageSize, Integer pageIndex) {
        Page<InventoryNoteItemBySale> page = new Page<>(pageIndex, pageSize);
        LambdaQueryWrapper<InventoryNoteItemBySale> lq = Wrappers.lambdaQuery();
        if (isNotInvoice != null && isNotInvoice) {
            lq.apply(" qty > invoice_qty");
        }
        if (!StringUtils.isNullOrEmpty(entId)) {
            lq.eq(InventoryNoteItemBySale::getEntId, entId);
        }
        if (!StringUtils.isNullOrEmpty(month)) {
            lq.eq(InventoryNoteItemBySale::getAccountMonthDesc, month);
        }
        if (!StringUtils.isNullOrEmpty(searchText)) {
            lq.and(s -> s.like(InventoryNoteItemBySale::getSkuCode, searchText.trim()).or().like(InventoryNoteItemBySale::getContractCode, searchText.trim()).like(InventoryNoteItemBySale::getInventoryNoteCode, searchText.trim()).or().like(InventoryNoteItemBySale::getPersonnelName, searchText));
        }
        lq.orderByAsc(InventoryNoteItemBySale::getAuditTime);
        return inventoryNoteItemBySaleMapper.selectPage(page, lq);
    }

    @Override
    public IPage<InventoryNoteExt> queryCheckNote(String code, Integer accountYear, Integer accountMonth, Integer pageSize, Integer pageIndex) {
        Page<InventoryNoteExt> page = new Page<>(pageIndex,pageSize);
        LambdaQueryWrapper<InventoryNoteExt> lq= Wrappers.lambdaQuery();

        List<String> noteTypeIds = new ArrayList();
        noteTypeIds.add(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.CHECK_IN).getId());
        noteTypeIds.add(inventoryNoteTypeService.queryOneByType(InventoryTypeEnum.CHECK_OUT).getId());
        lq.in(InventoryNoteExt::getNoteTypeId,noteTypeIds);

        if(!StringUtils.isNullOrEmpty(code)){
            lq.eq(InventoryNoteExt::getCode,code);
        }
//        if(accountYear!=null){
//            lq.eq(InventoryNoteExt::getAccountYear,accountYear);
//        }
//        if(accountMonth!=null){
//            lq.eq(InventoryNoteExt::getAccountMonth,accountMonth);
//        }
        lq.orderByDesc(InventoryNoteExt::getCreateTime);
        return inventoryNoteExtMapper.selectPage(page,lq);
    }

    @Override
    public List<InventoryNoteExt> queryNoteByContractCode(String contractCode) {
        LambdaQueryWrapper<InventoryNoteExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteExt::getContractCode, contractCode);
        return inventoryNoteExtMapper.selectList(lq);
    }

    @Override
    public int queryNoteCountByContractCode(String contractCode) {
        LambdaQueryWrapper<InventoryNoteExt> lq = Wrappers.lambdaQuery();
        lq.eq(InventoryNoteExt::getContractCode, contractCode);
        return inventoryNoteExtMapper.selectCount(lq);
    }
}
